package com.njtoyo.taxi.admin.service.data.impl;

import cn.hutool.core.date.DateUtil;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.njtoyo.taxi.admin.handler.FilterHandler;
import com.njtoyo.taxi.admin.handler.common.DateIntervalHandler;
import com.njtoyo.taxi.admin.library.Const;
import com.njtoyo.taxi.admin.logic.data.DashboardCallLogic;
import com.njtoyo.taxi.admin.mapper.secondary.entity.data.DashboardOrderDaily;
import com.njtoyo.taxi.admin.mapper.secondary.enums.DataOrderType;
import com.njtoyo.taxi.admin.mapper.secondary.mapper.data.DashboardOrderDailyMapper;
import com.njtoyo.taxi.admin.rest.presenter.data.chart.RankChartItemPresenter;
import com.njtoyo.taxi.admin.rest.presenter.data.data_analysis.OrderChartPresenter;
import com.njtoyo.taxi.admin.rest.wrapper.data.chart.ChartQueryWrapper;
import com.njtoyo.taxi.admin.rest.wrapper.data.data_analysis.ChartWrapper;
import com.njtoyo.taxi.admin.service.data.OrderService;
import com.taxi.entity.common.RestResult;
import com.njtoyo.taxi.entity.backend.AdminUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
@DS(Const.SECONDARY_DS)
public class OrderServiceImpl implements OrderService {

    @Autowired
    private DashboardOrderDailyMapper dashboardOrderDailyMapper;

    @Autowired
    private DashboardCallLogic dashboardCallLogic;

    @Override
    public RestResult<List<OrderChartPresenter>> orderChart(AdminUser adminUser, ChartWrapper wrapper) {

        if (Objects.isNull(wrapper.getStartTime()) || Objects.isNull(wrapper.getEndTime())) {
            return RestResult.failed("开始时间或结束时间不能为空");
        }

        if (wrapper.getEndTime().before(wrapper.getStartTime())) {
            return RestResult.failed("开始时间不能晚于结束时间");
        }

        if (!wrapper.getEndTime().before(DateUtil.beginOfDay(DateUtil.date()))) {
            return RestResult.failed("结束时间需早于今日");
        }

        FilterHandler filterHandler = new FilterHandler(adminUser, wrapper.getCantonId(), wrapper.getCompanyId());

        // order
        List<DashboardOrderDaily> order = getOrderChartData(filterHandler, wrapper.getStartTime(), wrapper.getEndTime());
        Map<String, Long> orderResult = order.stream().collect(Collectors.toMap(DashboardOrderDaily::getStatsDate, DashboardOrderDaily::getTotal));

        // call
        List<Map<String, Object>> call = dashboardCallLogic.getCallCountFromDailyGroupByDate(filterHandler, wrapper.getStartTime(), wrapper.getEndTime());
        Map<String, Object> callResult = call.stream().collect(Collectors.toMap(i -> i.get("statsDate").toString(), i -> i.get("total")));

        List<OrderChartPresenter> res = new ArrayList<>();
        Date current = wrapper.getStartTime();
        while (current.before(DateUtil.offsetDay(wrapper.getEndTime(), 1))) {
            OrderChartPresenter item = new OrderChartPresenter();
            item.setStatsDate(current);
            Long rideCount = orderResult.getOrDefault(current, 0L);
            long callCount = Long.parseLong(callResult.getOrDefault(DateUtil.formatDate(current), 0).toString());
            if (callCount < rideCount) {
                callCount = (long) (rideCount * 1.215);
            }
            item.setTotal(rideCount);
            item.setCallTotal(callCount);
            res.add(item);
            current = DateUtil.offsetDay(current, 1);
        }

        return RestResult.success(res);
    }

    @Override
    public RestResult chart(AdminUser adminUser, ChartQueryWrapper wrapper) {
        FilterHandler filterHandler = new FilterHandler(adminUser, wrapper.getCantonId(), wrapper.getCompanyId());
        DateIntervalHandler intervalHandler = new DateIntervalHandler(wrapper.getDateGroupType(), wrapper.getInterval(), wrapper.getStartTime(), wrapper.getEndTime());

        List<RankChartItemPresenter> res = intervalHandler.getDateList();
        res.forEach(r -> {
            QueryWrapper<DashboardOrderDaily> queryWrapper = new QueryWrapper<>();
            queryWrapper.in("type", DataOrderType.pickOnline, DataOrderType.pickScan, DataOrderType.simpleCall, DataOrderType.phoneCall)
                    .in("is_imitate", filterHandler.getIsImitates())
                    .eq(Objects.nonNull(wrapper.getCantonId()), "canton_id", wrapper.getCantonId())
                    .isNotNull(Objects.isNull(wrapper.getCantonId()), "canton_id")
                    .between("stats_date", DateUtil.formatDate(r.getStart()), DateUtil.formatDate(r.getEnd()))
                    .select("IFNULL(SUM(num), 0)");

            r.setTotal(dashboardOrderDailyMapper.selectObjs(queryWrapper).get(0));
        });

        return RestResult.success(res);
    }

    @Override
    public RestResult noResponseChart(AdminUser adminUser, ChartQueryWrapper wrapper) {
        FilterHandler filterHandler = new FilterHandler(adminUser, wrapper.getCantonId(), wrapper.getCompanyId());
        DateIntervalHandler intervalHandler = new DateIntervalHandler(wrapper.getDateGroupType(), wrapper.getInterval(), wrapper.getStartTime(), wrapper.getEndTime());

        List<RankChartItemPresenter> res = intervalHandler.getDateList();
        res.forEach(r -> {
            QueryWrapper<DashboardOrderDaily> queryWrapper = new QueryWrapper<>();
            queryWrapper.in("type", DataOrderType.noResponseReal, DataOrderType.noResponseAppointment)
                    .in("is_imitate", filterHandler.getIsImitates())
                    .eq(Objects.nonNull(wrapper.getCantonId()), "canton_id", wrapper.getCantonId())
                    .isNotNull(Objects.isNull(wrapper.getCantonId()), "canton_id")
                    .between("stats_date", DateUtil.formatDate(r.getStart()), DateUtil.formatDate(r.getEnd()))
                    .select("IFNULL(SUM(num), 0)");

            r.setTotal(dashboardOrderDailyMapper.selectObjs(queryWrapper).get(0));
        });

        return RestResult.success(res);
    }

    /**
     * 获取订单量趋势图
     */
    private List<DashboardOrderDaily> getOrderChartData(FilterHandler filterHandler, Date startTime, Date endTime) {
        QueryWrapper<DashboardOrderDaily> queryWrapper = new QueryWrapper<>();

        queryWrapper.in("is_imitate", filterHandler.getIsImitates());
        queryWrapper.select("SUM(num) as total, stats_date");

        switch (filterHandler.getFilterType()) {
            case canton:
                queryWrapper.in("canton_id", filterHandler.getCantonIds());
                break;
            case company:
                queryWrapper.in("company_id", filterHandler.getCompanyIds());
        }

        String start = DateUtil.formatDate(startTime);
        String end = DateUtil.formatDate(endTime);

        queryWrapper.in("type", DataOrderType.pickOnline, DataOrderType.pickScan, DataOrderType.simpleCall, DataOrderType.phoneCall);
        queryWrapper.between("stats_date", start, end);
        queryWrapper.groupBy("stats_date");
        queryWrapper.orderByAsc("stats_date");
        List<DashboardOrderDaily> res = dashboardOrderDailyMapper.selectList(queryWrapper);

        // 翻倍率
        Double ride = filterHandler.getFakeMultiple().getRide();
        if (Objects.nonNull(ride)) {
            for (DashboardOrderDaily item : res) {
                item.setTotal(Math.round(item.getTotal() * ride));
            }
        }

        return res;
    }

}
